import { WordSearcherState } from '../WordSearcher/reducer'
import * as _ from "lodash";
import { Dispatch } from "redux";
import Axios, { AxiosResponse } from "axios";
import { createAction, createAsyncAction, ActionType, createReducer } from "typesafe-actions";


export interface WordListIndexDto {
    wordValue: string;
}

export type WordListIndex = WordListIndexDto;

/**
 * ajax返回的要在reducer里被压平的word信息数组,现在包含了单词，以后可能包含每个单词的附加信息
 */
// export type WordListDto = WordListRecordDto[];
export interface WordListDto {
    count: number
    dtos: WordListIndexDto[]
}

/**
 * 在reducer里返回给组件的被压平的word信息
 * //todo 添加描述信息
 */
export interface WordListState {
    /**
     * wordlist组件每列的信息
     */
    dto: WordListDto;
    highlight: number;
}

export const setState = createAction('WORD_LIST/SET_STATE')<WordListState>();
export const highlight = createAction('WORD_LIST/HIGHLIGHT')<number>();
const asyncFetch = createAsyncAction(
    'WORD_LIST/FETCH/REQUEST',
    ['WORD_LIST/FETCH/SUCCESS', (res: WordListDto) => res],
    ['WORD_LIST/FETCH/FAILURE', (err: Error) => err],
    'WORD_LIST/FETCH/CANCEL',
)();
const asyncAdd = createAsyncAction(
    'WORD_LIST/ADD/REQUEST',
    ['WORD_LIST/ADD/SUCCESS', (res: string) => res],
    ['WORD_LIST/ADD/FAILURE', (err: Error) => err],
    'WORD_LIST/ADD/CANCEL',
)();
const asyncRemove = createAsyncAction(
    'WORD_LIST/REMOVE/REQUEST',
    ['WORD_LIST/REMOVE/SUCCESS', (res: string) => res],
    ['WORD_LIST/REMOVE/FAILURE', (err: Error) => err],
    'WORD_LIST/REMOVE/CANCEL',
)();

export type WordListActions =
    ActionType<typeof asyncFetch> | ActionType<typeof asyncAdd> | ActionType<typeof asyncRemove> | ActionType<typeof setState> |
    ActionType<typeof highlight>
    ;

export const add = (wordSearcherState: WordSearcherState) =>
    async (dispatch: Dispatch) => {
        const { wordValue } = wordSearcherState.wordConditionDto
        if (wordValue !== '' && wordValue) {
            Axios.post(`wordBase/${wordValue.trim()}/${wordSearcherState.wordConditionDto.wordTagValue}`)
                .then(() => {
                    if (!_.isUndefined(wordSearcherState.wordConditionDto.wordValue)) {
                        dispatch(asyncAdd.success(wordSearcherState.wordConditionDto.wordValue))
                    }
                })
        }
    }

export const fetch = (page: number = 0, size: number = 10) =>
    async (dispatch: Dispatch) => {
        Axios.get<WordListDto>(`wordList?page=${page}&size=${size}`)
            .then((response) => dispatch(asyncFetch.success(response.data)))
    }

/**
 * 根据单词和标签查找单词列表
 * //todo 以后负责分发url
 * @param baseVo 
 */

export const fetchByCondition = (state: WordSearcherState, page: number = 0, size: number = 10) =>
    async (dispatch: Dispatch) =>
        Axios.post<WordSearcherState, AxiosResponse<WordListDto>>(`wordList/condition?page=${page}&size=${size}`, state.wordConditionDto)
            .then((response) => dispatch(asyncFetch.success(response.data)))

export const remove = (wordValue: string) =>
    async (dispatch: Dispatch) =>
        Axios.delete(`wordBase/${wordValue}`)
            .then(() => dispatch(asyncRemove.success(wordValue)))


const initialState: WordListState = {
    dto: {
        count: 0,
        dtos: []
    },
    highlight: 0
};


export const Reducer = createReducer<WordListState, WordListActions>(initialState)
    .handleAction(setState, (_, action) => action.payload)
    .handleAction(asyncFetch.success, (state, action) => {
        const newState = { ...state }
        newState.dto = action.payload
        return newState
    })
    .handleAction(asyncAdd.success, (state, action) => {
        const newState = { ...state }
        const existIndex = newState.dto.dtos.findIndex(e => e.wordValue === action.payload)
        if (existIndex === -1) {
            newState.dto.dtos.push({ wordValue: action.payload })
            newState.dto.count = newState.dto.count + 1
        }
        return newState
    })
    .handleAction(asyncRemove.success, (state, action) => {
        const newState = { ...state }
        _.remove(newState.dto.dtos, (index) => index.wordValue === action.payload)
        return newState
    })
    .handleAction(highlight, (state, action) => {
        const newState = { ...state }
        newState.highlight = action.payload
        return newState
    })